use std::sync::{Arc, Mutex};

use arm_linux_boot::ArmLinuxBoot;
use bitops::{deposit32, extract32};
use cpu::current_cpu_index;
use interrupt::IntBackendDevice;
use memory::{MemTxAttr, MemTxResult};
use objectid::ObjectId;
use tracelog::{log_faltal, log_guest_error};

use self::{
    common::{
        GIC_INTERNAL, GIC_MAXIRQ, GIC_MAX_LR, GIC_MAX_PRIORITY_BITS, GIC_MIN_ABPR, GIC_MIN_BPR,
        GIC_MIN_PRIORITY_BITS, GIC_NCPU, GIC_NCPU_VCPU, GIC_NR_APRS, GIC_NR_SGIS,
        GIC_VIRT_MAX_GROUP_PRIO_BITS, GIC_VIRT_MIN_ABPR, GIC_VIRT_MIN_BPR, GIC_VIRT_NR_APRS,
    },
    internal::{
        gich_lr_cpuid, gich_lr_eoi, gich_lr_group, gich_lr_hw, gich_lr_priority, gich_lr_state,
        gich_lr_virt_id, R_GICH_HCR_EOICount_MASK, R_GICH_HCR_EOICount_SHIFT,
        R_GICH_MISR_VGrp0D_MASK, R_GICH_MISR_VGrp0E_MASK, R_GICH_MISR_VGrp1D_MASK,
        R_GICH_MISR_VGrp1E_MASK, ALL_CPU_MASK, GICC_CTLR_ACK_CTL, GICC_CTLR_CBPR,
        GICC_CTLR_EN_GRP0, GICC_CTLR_EN_GRP1, GICC_CTLR_EOIMODE, GICC_CTLR_EOIMODE_NS,
        GICC_CTLR_FIQ_EN, GICC_CTLR_V1_MASK, GICC_CTLR_V1_S_MASK, GICC_CTLR_V2_MASK,
        GICC_CTLR_V2_S_MASK, GICD_CTLR_EN_GRP0, GICD_CTLR_EN_GRP1, GICH_HCR_MASK, GICH_LR_MASK,
        GICH_LR_STATE_INVALID, GICH_LR_STATE_PENDING, R_GICH_HCR_EN_MASK, R_GICH_HCR_LRENPIE_MASK,
        R_GICH_HCR_NPIE_MASK, R_GICH_HCR_UIE_MASK, R_GICH_HCR_VGRP0DIE_MASK,
        R_GICH_HCR_VGRP0EIE_MASK, R_GICH_HCR_VGRP1DIE_MASK, R_GICH_HCR_VGRP1EIE_MASK,
        R_GICH_MISR_EOI_MASK, R_GICH_MISR_LRENP_MASK, R_GICH_MISR_NP_MASK, R_GICH_MISR_U_MASK,
    },
    trace::GICv2Trace,
};
use crate::gicv2::internal::REV_11MPCORE;

mod builder;
mod common;
mod interface;
mod internal;
mod trace;

pub use builder::*;

#[derive(Default, Clone, Copy)]
struct GICv2IrqState {
    // enable bits 仅用于存储 percpu 中断
    enabled: u8,
    pending: u8,
    active: u8,
    level: u8,
    // 0 = N:N, 1 = 1:N
    model: bool,
    // true: edge-triggered, false: level-triggered
    edge_trigger: bool,
    group: u8,
}

struct GICv2StateInner {
    // GICD_CTLR: 对于带安全拓展的 GIC, 这个寄存器的 NS banked 版本仅仅是 S banked 版本 bit 1 的别名
    ctlr: u32,
    // GICC_CTLR: 同样的, NS banked 版本仅是 S banked 版本寄存器 bits 的别名, 所以状态只需要存储 S banked 版本
    cpu_ctlr: [u32; GIC_NCPU_VCPU],

    irq_state: [GICv2IrqState; GIC_MAXIRQ],
    irq_target: [u8; GIC_MAXIRQ],
    // 每个私有中断对应 GIC_NCPU 个 cpu
    priority1: [[u8; GIC_NCPU]; GIC_INTERNAL],
    priority2: [u8; GIC_MAXIRQ - GIC_INTERNAL],
    // 对于目标 CPU 上的每个 SGI, 存储 8 bits, 表示哪个源 CPU 使该 SGI 挂起在目标 CPU 上.
    // 这些字节对应于目标 CPU 读取的 GIC_SPENDSGIR* 寄存器中的字节
    sgi_pending: [[u8; GIC_NCPU]; GIC_NR_SGIS],

    priority_mask: [u16; GIC_NCPU_VCPU],
    running_priority: [u16; GIC_NCPU_VCPU],
    current_pending: [u16; GIC_NCPU_VCPU],
    n_prio_bits: u32,

    // 如果将不带安全拓展的 GICv2 提供给客户机, 那么客户机可以配置 GICC_CTLR 来配置 abpr 的一个bit位,
    // 对于具有安全拓展的 GIC, 使用 bpr 作为安全副本, 使用 abpr 作为寄存器的非安全副本存储
    bpr: [u8; GIC_NCPU_VCPU],
    abpr: [u8; GIC_NCPU_VCPU],

    // APR 是实现定义的, 所以这里为 SIMINK 的逻辑实现选择一个与 KVM ABI 布局相同的布局:
    // 如果抢占级别 X 的中断是 active 的, 则 APRn[X mod 32] == 0b1, 其中 n = X / 32, 否则该位清除.
    apr: [[u32; GIC_NCPU]; GIC_NR_APRS],
    nsapr: [[u32; GIC_NCPU]; GIC_NR_APRS],

    // 虚拟接口控制寄存器
    h_hcr: [u32; GIC_NCPU],
    h_misr: [u32; GIC_NCPU],
    h_lr: [[u32; GIC_NCPU]; GIC_MAX_LR],
    h_apr: [u32; GIC_NCPU],

    // 在此 GIC 实例中实现的 LRs 数量
    num_lrs: u32,

    num_cpu: u32,

    num_irq: u32,
    // 对于 GIC 体系结构规范版本 1 或者 2, Revision 可以是 1 或者 2,
    // 对于遗留的 11MPCore GIC Revision 可以是 0.
    revision: u32,
    security_extn: bool,
    virt_extn: bool,
    // 在复位时, 将 IRQs 配置为 group 1(NS)?
    irq_reset_nonsecure: bool,
}

struct GICv2StateInterface {
    parent_irq: [Arc<IntBackendDevice>; GIC_NCPU],
    parent_fiq: [Arc<IntBackendDevice>; GIC_NCPU],
    parent_virq: [Arc<IntBackendDevice>; GIC_NCPU],
    parent_vfiq: [Arc<IntBackendDevice>; GIC_NCPU],
    maintenance_irq: [Arc<IntBackendDevice>; GIC_NCPU],
}

/// `GICv2` 硬件状态
pub struct GICv2State {
    inner: Arc<Mutex<GICv2StateInner>>,
    interface: GICv2StateInterface,
    name: String,
}

const DEBUG_GIC: Option<&'static str> = option_env!("SIMINK_DEBUG_GICV2");

const fn debug_gic_enable() -> bool {
    DEBUG_GIC.is_some()
}

const GIC_ID_11MPCORE: [u8; 12] =
    [0x00, 0x00, 0x00, 0x00, 0x90, 0x13, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1];
const GIC_ID_GICV1: [u8; 12] =
    [0x04, 0x00, 0x00, 0x00, 0x90, 0xb3, 0x1b, 0x00, 0x0d, 0xf0, 0x05, 0xb1];
const GIC_ID_GICV2: [u8; 12] =
    [0x04, 0x00, 0x00, 0x00, 0x90, 0xb4, 0x2b, 0x00, 0x0d, 0xf0, 0x05, 0xb1];

impl GICv2StateInner {
    #[inline]
    fn gic_get_current_cpu(&self) -> usize {
        if self.num_cpu > 1 {
            return current_cpu_index() as usize;
        }
        0
    }

    #[inline]
    fn gic_get_current_vcpu(&self) -> usize {
        self.gic_get_current_cpu() + GIC_NCPU
    }

    // 如果此 GIC 配置具有中断组, 则返回 true, 如果是 GICv2 或者具有安全拓展的 GICv1 返回 true
    #[inline]
    fn gic_has_groups(&self) -> bool {
        self.revision == 2 || self.security_extn
    }

    #[inline]
    fn gic_cpu_ns_access(&self, cpu: usize, attrs: MemTxAttr) -> bool {
        !self.gic_is_vcpu(cpu) && self.security_extn && !attrs.secure
    }

    #[inline]
    fn gic_get_best_irq(
        &self,
        cpu: usize,
        best_irq: &mut i32,
        best_prio: &mut i32,
        group: &mut i32,
    ) {
        let cm = 1 << cpu;

        *best_irq = 1023;
        *best_prio = 0x100;

        for irq in 0..self.num_irq as usize {
            if (self.gic_dist_test_enabled(irq, cm)
                && self.gic_test_pending(irq, cm)
                && (!self.gic_dist_test_active(irq, cm))
                && (irq < GIC_INTERNAL || self.gic_dist_target(irq) & cm != 0))
                && (self.gic_dist_get_priority_i(irq, cpu) < *best_prio as u8)
            {
                *best_prio = self.gic_dist_get_priority_i(irq, cpu) as i32;
                *best_irq = irq as i32;
            }
        }

        if *best_irq < 1023 {
            *group = self.gic_dist_test_group(*best_irq as usize, cm) as i32;
        }
    }

    #[inline]
    fn gic_get_best_virq(
        &self,
        cpu: usize,
        best_irq: &mut i32,
        best_prio: &mut i32,
        group: &mut i32,
    ) {
        *best_irq = 1023;
        *best_prio = 0x100;

        for lr_idx in 0..self.num_lrs as usize {
            let lr_entry = &self.h_lr[lr_idx][cpu];
            let state = gich_lr_state(*lr_entry);

            if state == GICH_LR_STATE_PENDING {
                let prio = gich_lr_priority(*lr_entry);

                if prio < *best_prio as u32 {
                    *best_prio = prio as i32;
                    *best_irq = gich_lr_virt_id(*lr_entry) as i32;
                    *group = gich_lr_group(*lr_entry) as i32;
                }
            }
        }
    }

    // 如果为给定 cpu 和至少一个给定组启用了 IRQ 信令, 则返回 true;
    // - 在非 virt 情况下, 必须为其中一个给定组启用分发器
    // - 在 virt 情况下, 必须使能虚接口
    // - 在所有情况下, (v)CPU 接口必须为其中一个给定组启用
    #[inline]
    fn gic_irq_signaling_enabled(&self, cpu: usize, virt: bool, group_mask: u32) -> bool {
        let cpu_iface = if virt { cpu + GIC_NCPU } else { cpu };

        if !virt && self.ctlr & group_mask == 0 {
            return false;
        }

        if virt && self.h_hcr[cpu] & R_GICH_HCR_EN_MASK == 0 {
            return false;
        }

        if self.cpu_ctlr[cpu_iface] & group_mask == 0 {
            return false;
        }

        true
    }

    // TODO: 许多调用此例程的地方可以进行优化.
    // 在启用或挂起位更改后更新中断状态.
    #[inline]
    fn gic_update_internal(&mut self, virt: bool, interface: &GICv2StateInterface) {
        let s = if virt { String::from("vcpu") } else { String::from("cpu") };

        let mut best_irq = 0;
        let mut best_prio = 0;
        let mut group = 0;

        let irq_lines = if virt { &interface.parent_virq } else { &interface.parent_irq };
        let fiq_lines = if virt { &interface.parent_vfiq } else { &interface.parent_fiq };
        for cpu in 0..self.num_cpu as usize {
            let cpu_iface = if virt { cpu + GIC_NCPU } else { cpu };

            self.current_pending[cpu_iface] = 1023;
            if !self.gic_irq_signaling_enabled(
                cpu,
                virt,
                (GICD_CTLR_EN_GRP0 | GICD_CTLR_EN_GRP1) as u32,
            ) {
                irq_lines[cpu].int_lower();
                fiq_lines[cpu].int_lower();
                continue;
            }

            if virt {
                self.gic_get_best_virq(cpu, &mut best_irq, &mut best_prio, &mut group);
            } else {
                self.gic_get_best_irq(cpu, &mut best_irq, &mut best_prio, &mut group);
            }

            if best_irq != 1023 {
                GICv2Trace::trace_gic_update_bestirq(
                    &s,
                    &cpu,
                    &(best_irq as usize),
                    &(best_prio as usize),
                    &(self.priority_mask[cpu_iface] as usize),
                    &(self.running_priority[cpu_iface] as usize),
                );
            }

            let mut irq_level = false;
            let mut fiq_level = false;

            if best_prio < self.priority_mask[cpu_iface] as i32 {
                self.current_pending[cpu_iface] = best_irq as u16;
                if best_prio < self.running_priority[cpu_iface] as i32
                    && self.gic_irq_signaling_enabled(cpu, virt, 1 << group)
                {
                    if group == 0 && self.cpu_ctlr[cpu_iface] & GICC_CTLR_FIQ_EN as u32 != 0 {
                        if debug_gic_enable() {
                            println!("Raised pending FIQ {} (cpu {})", best_irq, cpu_iface);
                        }
                        fiq_level = true;
                        GICv2Trace::trace_gic_update_set_irq(&cpu, &s, &fiq_level);
                    } else {
                        if debug_gic_enable() {
                            println!("Raised pending IRQ {} (cpu {})", best_irq, cpu_iface);
                        }
                        irq_level = true;
                        GICv2Trace::trace_gic_update_set_irq(&cpu, &s, &irq_level);
                    }
                }
            }

            irq_lines[cpu].set_int(irq_level);
            fiq_lines[cpu].set_int(fiq_level);
        }
    }

    fn gic_update(&mut self, interface: &GICv2StateInterface) {
        self.gic_update_internal(false, interface);
    }

    // 如果此 LR 为空, 则返回 true, 即设置了 ELRSR 中的相应位
    #[inline]
    fn gic_lr_entry_is_free(&self, entry: u32) -> bool {
        gich_lr_state(entry) == GICH_LR_STATE_INVALID
            && (gich_lr_hw(entry) != 0 || gich_lr_eoi(entry) == 0)
    }

    // 如果此 LR 应触发 EOI 维护中断, 即 EISR 中相应的位被设置, 则返回 true
    #[inline]
    fn gic_lr_entry_is_eoi(&self, entry: u32) -> bool {
        gich_lr_state(entry) == GICH_LR_STATE_INVALID
            && gich_lr_hw(entry) == 0
            && gich_lr_eoi(entry) != 0
    }

    #[inline]
    fn gic_extract_lr_info(
        &self,
        cpu: usize,
        num_eoi: &mut usize,
        num_valid: &mut usize,
        num_pending: &mut usize,
    ) {
        *num_eoi = 0;
        *num_valid = 0;
        *num_pending = 0;

        for lr_idx in 0..self.num_lrs as usize {
            let entry = &self.h_lr[lr_idx][cpu];

            if self.gic_lr_entry_is_eoi(*entry) {
                *num_eoi += 1;
            }

            if gich_lr_state(*entry) != GICH_LR_STATE_INVALID {
                *num_valid += 1;
            }

            if gich_lr_state(*entry) == GICH_LR_STATE_PENDING {
                *num_pending += 1;
            }
        }
    }

    fn gic_compute_misr(&mut self, cpu: usize) {
        let mut value = 0;
        let vcpu = cpu + GIC_NCPU;

        let mut num_eoi = 0;
        let mut num_valid = 0;
        let mut num_pending = 0;
        self.gic_extract_lr_info(cpu, &mut num_eoi, &mut num_valid, &mut num_pending);

        // EOI
        if num_eoi != 0 {
            value |= R_GICH_MISR_EOI_MASK;
        }

        // U: 如果仅有 0 或者 1 个 LR 条目可用则返回 true
        if self.h_hcr[cpu] & R_GICH_HCR_UIE_MASK != 0 && num_valid < 2 {
            value |= R_GICH_MISR_U_MASK;
        }

        // LRENP: EOICount 不是 0
        if self.h_hcr[cpu] & R_GICH_HCR_LRENPIE_MASK != 0
            && self.h_hcr[cpu] & R_GICH_HCR_EOICount_MASK != 0
        {
            value |= R_GICH_MISR_LRENP_MASK;
        }

        // NP: 没有挂起的中断
        if self.h_hcr[cpu] & R_GICH_HCR_NPIE_MASK != 0 && num_pending == 0 {
            value |= R_GICH_MISR_NP_MASK;
        }

        // VGrp0E: group0 virq 信号被激活
        if self.h_hcr[cpu] & R_GICH_HCR_VGRP0EIE_MASK != 0
            && self.cpu_ctlr[vcpu] & GICC_CTLR_EN_GRP0 as u32 != 0
        {
            value |= R_GICH_MISR_VGrp0E_MASK;
        }

        // VGrp0D: group0 virq 信号被禁用
        if self.h_hcr[cpu] & R_GICH_HCR_VGRP0DIE_MASK != 0
            && self.cpu_ctlr[vcpu] & GICC_CTLR_EN_GRP0 as u32 == 0
        {
            value |= R_GICH_MISR_VGrp0D_MASK;
        }

        // VGrp1E: group1 virq 信号被激活
        if self.h_hcr[cpu] & R_GICH_HCR_VGRP1EIE_MASK != 0
            && self.cpu_ctlr[vcpu] & GICC_CTLR_EN_GRP1 as u32 != 0
        {
            value |= R_GICH_MISR_VGrp1E_MASK;
        }

        // VGrp1D: group1 virq 信号被禁用
        if self.h_hcr[cpu] & R_GICH_HCR_VGRP1DIE_MASK != 0
            && self.cpu_ctlr[vcpu] & GICC_CTLR_EN_GRP1 as u32 == 0
        {
            value |= R_GICH_MISR_VGrp1D_MASK;
        }

        self.h_misr[cpu] = value;
    }

    fn gic_update_maintenance(&mut self, interface: &GICv2StateInterface) {
        for cpu in 0..self.num_cpu as usize {
            self.gic_compute_misr(cpu);
            let maint_level = self.h_hcr[cpu] & R_GICH_HCR_EN_MASK != 0 && self.h_misr[cpu] != 0;

            GICv2Trace::trace_gic_update_maintenance_irq(&cpu, &(maint_level as usize));
            interface.maintenance_irq[cpu].set_int(maint_level);
        }
    }

    fn gic_update_virt(&mut self, interface: &GICv2StateInterface) {
        self.gic_update_internal(true, interface);
        self.gic_update_maintenance(interface);
    }

    fn gic_set_irq_11mpcore(&mut self, irq: usize, level: bool, cm: u8, target: u8) {
        if level {
            self.gic_dist_set_level(irq, cm);
            if self.gic_dist_test_edge_trigger(irq) || self.gic_dist_test_enabled(irq, cm) {
                if debug_gic_enable() {
                    println!("Set {} pending mask 0x{:x}", irq, target);
                }
                self.gic_dist_set_pending(irq, target);
            }
        } else {
            self.gic_dist_clear_level(irq, cm);
        }
    }

    fn gic_set_irq_generic(&mut self, irq: usize, level: bool, cm: u8, target: u8) {
        if level {
            self.gic_dist_set_level(irq, cm);
            if debug_gic_enable() {
                println!("Set {} pending mask 0x{:x}", irq, target);
            }
            if self.gic_dist_test_edge_trigger(irq) {
                self.gic_dist_set_pending(irq, target);
            }
        } else {
            self.gic_dist_clear_level(irq, cm);
        }
    }

    // 处理外部 IRQ 输入中的更改
    fn gic_set_irq(&mut self, mut irq: usize, level: bool, interface: &GICv2StateInterface) {
        let mut cm;
        let mut target;
        // irq 参数的含义如下:
        // [0..N-1]: 外部中断
        // [N..N+31]: CPU 0 的 PPI(internal) 中断
        // [N+32..N+63]: CPU 1 的 PPI 中断
        // ...
        if irq < self.num_irq as usize - GIC_INTERNAL {
            // 第一条外部输入线是内部中断 32
            cm = ALL_CPU_MASK;
            irq += GIC_INTERNAL;
            target = self.gic_dist_target(irq);
        } else {
            irq -= self.num_irq as usize - GIC_INTERNAL;
            let cpu = irq / GIC_INTERNAL;
            irq %= GIC_INTERNAL;
            cm = 1 << cpu;
            target = cm as u8;
        }

        debug_assert!(irq >= GIC_NR_SGIS);
        if level == self.gic_dist_test_level(irq, cm as u8) {
            return;
        }

        if self.revision == REV_11MPCORE as u32 {
            self.gic_set_irq_11mpcore(irq, level, cm as u8, target);
        } else {
            self.gic_set_irq_generic(irq, level, cm as u8, target);
        }
        GICv2Trace::trace_gic_set_irq(&irq, &level, &cm, &(target as usize));

        self.gic_update(interface);
    }

    fn gic_get_current_pending_irq(&mut self, cpu: usize, attrs: MemTxAttr) -> u16 {
        let pending_irq = self.current_pending[cpu];

        if pending_irq < GIC_MAXIRQ as u16 && self.gic_has_groups() {
            let group = self.gic_test_group(pending_irq as usize, cpu);

            // 在一个没有安全拓展的 GIC, 读寄存器行为与使用它们对 GIC 进行安全访问的方式相同
            let secure = !self.gic_cpu_ns_access(cpu, attrs);

            if group && secure && self.cpu_ctlr[cpu] & GICC_CTLR_ACK_CTL as u32 == 0 {
                // 如果 AckCtl bit 被设置了, group1 中断仅可以安全访问
                return 1022;
            }
        }
        pending_irq
    }

    fn gic_get_group_priority(&mut self, cpu: usize, irq: usize) -> u8 {
        // 返回指定中断的组优先级(这是其优先级的最高位, 由适用的二进制点寄存器确定掩码的位数)
        let bpr = if self.gic_has_groups()
            && self.cpu_ctlr[cpu] & GICC_CTLR_CBPR as u32 == 0
            && self.gic_test_group(irq, cpu)
        {
            let tmp = self.abpr[cpu] - 1;
            debug_assert!(tmp != u8::MAX);
            tmp
        } else {
            self.bpr[cpu]
        };

        // BPR = 0 表示组优先级位为[7:1];
        // BPR = 1 表示它们是[7:2], 以此类推, 直到 BPR 为 7 表示根本没有组优先级位.
        let mask = u8::MAX << ((bpr & 7) + 1);
        self.gic_get_priority(irq, cpu) & mask
    }

    fn gic_activate_irq(&mut self, cpu: usize, irq: usize) {
        // 为这个 IRQ 设置适当的活动优先级寄存器位, 并更新运行优先级
        let prio = self.gic_get_group_priority(cpu, irq);
        let min_bpr = if self.gic_is_vcpu(cpu) { GIC_VIRT_MIN_BPR } else { GIC_MIN_BPR };
        let preemption_level = prio >> (min_bpr + 1);
        let regno = preemption_level / 32;
        let bitno = preemption_level % 32;
        let papr = if self.gic_is_vcpu(cpu) {
            debug_assert_eq!(regno, 0);
            &mut self.h_apr[self.gic_get_vcpu_real_id(cpu)]
        } else if self.gic_has_groups() && self.gic_test_group(irq, cpu) {
            &mut self.nsapr[regno as usize][cpu]
        } else {
            &mut self.apr[regno as usize][cpu]
        };

        *papr |= 1 << bitno;

        self.running_priority[cpu] = prio as u16;
        self.gic_set_active(irq, cpu);
    }

    fn gic_get_prio_from_apr_bits(&self, cpu: usize) -> u32 {
        // 根据活动优先级寄存器中的设置位重新计算该 CPU 的当前运行优先级
        if self.gic_is_vcpu(cpu) {
            let apr = self.h_apr[self.gic_get_vcpu_real_id(cpu)];
            if apr != 0 {
                return apr.trailing_zeros() << (GIC_VIRT_MIN_BPR + 1);
            } else {
                return 0x100;
            }
        }

        for i in 0..GIC_NR_APRS {
            let apr = self.apr[i][cpu] | self.nsapr[i][cpu];
            if apr == 0 {
                continue;
            }
            return (i as u32 * 32 + apr.trailing_zeros()) << (GIC_MIN_BPR + 1);
        }

        0x100
    }

    fn gic_drop_prio(&mut self, cpu: usize, group: i32) {
        // 删除指定组中当前活动中断的优先级
        //
        // 请注意, 我们可以保证(因为要求嵌套GICC_IAR读[激活中断并提高优先级]与GICC_EOIR写[降低中断的优先级]),
        // 我们正在调用的中断是最高优先级的活动中断, 这意味着它在 APR 寄存器中具有最低的设置位.
        //
        // 如果客户机不遵循排序约束, 那么 GIC 的行为是不可预测的, 这对我们来说意味着 APR 寄存器的值可能变得不正确
        // 运行优先级将是错误的, 因此应该抢占的中断可能不会这样做, 而不应该抢占的中断可能会这样做.
        if self.gic_is_vcpu(cpu) {
            let rcpu = self.gic_get_vcpu_real_id(cpu);

            if self.h_apr[rcpu] != 0 {
                // 清除最低位
                self.h_apr[rcpu] &= self.h_apr[rcpu] - 1;
            }
        } else {
            for i in 0..GIC_NR_APRS {
                let papr = if group != 0 { &mut self.nsapr[i][cpu] } else { &mut self.apr[i][cpu] };
                if *papr == 0 {
                    continue;
                }
                // 清除最低位
                *papr &= *papr - 1;
                break;
            }
        }

        self.running_priority[cpu] = self.gic_get_prio_from_apr_bits(cpu) as u16;
    }

    #[inline]
    fn gic_clear_pending_sgi(&mut self, irq: usize, cpu: usize) -> usize {
        if self.gic_is_vcpu(cpu) {
            // 查找 SGI 的源 CPU, 并在 sgi_pending 映射中将其清除.
            // 如果 SGI 没有从任何 CPU 挂起, 则返回 src 并清除该 CPU 上的整个挂起状态.
            debug_assert!(self.sgi_pending[irq][cpu] != 0);
            let src = self.sgi_pending[irq][cpu].trailing_zeros();
            self.sgi_pending[irq][cpu] &= !(1 << src);
            if self.sgi_pending[irq][cpu] == 0 {
                self.gic_clear_pending(irq, cpu);
            }
            irq | ((src as usize & 0x7) << 10)
        } else {
            let lr_entry = self.gic_get_lr_entry(irq, cpu);
            let src = gich_lr_cpuid(*lr_entry);

            self.gic_clear_pending(irq, cpu);
            irq | (src as usize) << 10
        }
    }

    fn gic_acknowledge_irq(
        &mut self,
        cpu: usize,
        attrs: MemTxAttr,
        interface: &GICv2StateInterface,
    ) -> u32 {
        // gic_get_current_pending_irq() 将返回 1022 或 1023 适当的情况下,
        // 此 GIC 支持分组和挂起的中断是在错误的组.
        let irq = self.gic_get_current_pending_irq(cpu, attrs);
        let s = if self.gic_is_vcpu(cpu) { String::from("vcpu") } else { String::from("cpu") };
        GICv2Trace::trace_gic_acknowledge_irq(&s, &self.gic_get_vcpu_real_id(cpu), &(irq as usize));

        if irq >= GIC_MAXIRQ as u16 {
            if debug_gic_enable() {
                println!("ACK, no pending interrupt or it is hidden: {}", irq);
            }
            return irq as u32;
        }

        if self.gic_get_priority(irq as usize, cpu) >= self.running_priority[cpu] as u8 {
            if debug_gic_enable() {
                println!("ACK, pending interrupt ({}) has insufficient priority", irq);
            }
            return 1023;
        }

        self.gic_activate_irq(cpu, irq as usize);

        let ret = if self.revision == REV_11MPCORE as u32 {
            // 清除level和边缘触发中断的挂起标志. 一旦level触发的 irq 变得不活跃,
            // 它们将被重新激活
            self.gic_clear_pending(irq as usize, cpu);
            irq
        } else if irq < GIC_NR_SGIS as u16 {
            self.gic_clear_pending_sgi(irq as usize, cpu) as u16
        } else {
            self.gic_clear_pending(irq as usize, cpu);
            irq
        };

        if self.gic_is_vcpu(cpu) {
            self.gic_update_virt(interface);
        } else {
            self.gic_update(interface);
        }
        if debug_gic_enable() {
            println!("ACK {}", irq);
        }
        ret as u32
    }

    fn gic_fullprio_mask(&self, cpu: usize) -> u32 {
        // 返回一个掩码字, 从中断的优先级值中清除未实现的优先级位.
        // (不要与组优先级混淆, 后者的掩码取决于 BPR)
        let pri_bits = if self.gic_is_vcpu(cpu) {
            GIC_VIRT_MAX_GROUP_PRIO_BITS as u32
        } else {
            self.n_prio_bits
        };
        u32::MAX << (8 - pri_bits)
    }

    fn gic_dist_set_priority(&mut self, cpu: usize, irq: usize, mut val: u8, attrs: MemTxAttr) {
        if self.security_extn && !attrs.secure {
            if !self.gic_dist_test_group(irq, 1 << cpu) {
                // group0 IRQ 的 非安全访问忽略
                return;
            }
            // 非安全视图
            val = 0x80 | (val >> 1);
        }

        val &= self.gic_fullprio_mask(cpu) as u8;

        if irq < GIC_INTERNAL {
            self.priority1[irq][cpu] = val;
        } else {
            self.priority2[irq - GIC_INTERNAL] = val;
        }
    }

    fn gic_dist_get_priority(&self, cpu: usize, irq: usize, attrs: MemTxAttr) -> u32 {
        let mut prio = self.gic_dist_get_priority_i(irq, cpu);

        if self.security_extn && !attrs.secure {
            if !self.gic_dist_test_group(irq, 1 << cpu) {
                // group0 IRQ 非安全访问不能读优先级
                return 0;
            }
            // 非安全视图
            prio <<= 1;
        }
        prio as u32 & self.gic_fullprio_mask(cpu)
    }

    fn gic_set_priority_mask(&mut self, cpu: usize, mut pmask: u8, attrs: MemTxAttr) {
        if self.gic_cpu_ns_access(cpu, attrs) {
            if self.priority_mask[cpu] & 0x80 != 0 {
                // 上半部分优先级掩码
                pmask = 0x80 | (pmask >> 1);
            } else {
                // 非安全忽略
                return;
            }
        }
        self.priority_mask[cpu] = (pmask as u32 & self.gic_fullprio_mask(cpu)) as u16;
    }

    fn gic_get_priority_mask(&self, cpu: usize, attrs: MemTxAttr) -> u32 {
        let mut pmask = self.priority_mask[cpu];

        if self.gic_cpu_ns_access(cpu, attrs) {
            if pmask & 0x80 != 0 {
                // 优先级掩码为上半部分, 返回非安全视图
                pmask = (pmask << 1) & 0xff;
            } else {
                // 优先级掩码在下半部分, RAZ
                pmask = 0;
            }
        }
        pmask as u32
    }

    fn gic_get_cpu_control(&self, cpu: usize, attrs: MemTxAttr) -> u32 {
        let mut ret = self.cpu_ctlr[cpu];

        if self.gic_cpu_ns_access(cpu, attrs) {
            // 从 S bank 视图的正确位构建 GICC_CTLR 的 NS bank 视图.
            // 不需要移动旁路控制位, 因为不实现 GIC 架构的(IMPDEF)部分.
            ret = (ret & (GICC_CTLR_EN_GRP1 | GICC_CTLR_EOIMODE_NS) as u32) >> 1;
        }
        ret
    }

    fn gic_set_cpu_control(&mut self, cpu: usize, value: u32, attrs: MemTxAttr) {
        if self.gic_cpu_ns_access(cpu, attrs) {
            // NS 视图只能在寄存器中写入某些位, 其余部分不变
            let mut mask = GICC_CTLR_EN_GRP1;
            if self.revision == 2 {
                mask |= GICC_CTLR_EOIMODE_NS;
            }
            self.cpu_ctlr[cpu] &= !mask as u32;
            self.cpu_ctlr[cpu] |= (value << 1) & mask as u32;
        } else {
            let mask = if self.revision == 2 {
                if self.security_extn { GICC_CTLR_V2_S_MASK } else { GICC_CTLR_V2_MASK }
            } else if self.security_extn {
                GICC_CTLR_V1_S_MASK
            } else {
                GICC_CTLR_V1_MASK
            };
            self.cpu_ctlr[cpu] = value & mask;
        }
        if debug_gic_enable() {
            println!(
                "CPU Interface {}: Group0 Interrupts {}abled, Group1 Interrupts {}abled",
                cpu,
                if self.cpu_ctlr[cpu] & GICC_CTLR_EN_GRP0 as u32 != 0 { "En" } else { "Dis" },
                if self.cpu_ctlr[cpu] & GICC_CTLR_EN_GRP1 as u32 != 0 { "En" } else { "Dis" }
            );
        }
    }

    fn gic_get_running_priority(&self, cpu: usize, attrs: MemTxAttr) -> u8 {
        if self.revision != REV_11MPCORE as u32 && self.running_priority[cpu] > 0xff {
            // 空闲优先级
            return 0xff;
        }

        if self.gic_cpu_ns_access(cpu, attrs) {
            if self.running_priority[cpu] & 0x80 != 0 {
                // 运行优先级在上半部分; 返回优先级的非安全视图
                (self.running_priority[cpu] as u8) << 1
            } else {
                // 运行优先级在下半部分: RAZ
                0
            }
        } else {
            self.running_priority[cpu] as u8
        }
    }

    // 如果我们应该分割优先级下降和中断停用, 即是否设置了相关的 EOIMode 位, 返回 true
    fn gic_eoi_split(&self, cpu: usize, attrs: MemTxAttr) -> bool {
        if self.revision != 2 {
            // 在 GICv2 之前, prio-drop 和 deactivate 是不可分割的
            return false;
        }
        if self.gic_cpu_ns_access(cpu, attrs) {
            return self.cpu_ctlr[cpu] & GICC_CTLR_EOIMODE_NS as u32 != 0;
        }
        self.cpu_ctlr[cpu] & GICC_CTLR_EOIMODE as u32 != 0
    }

    fn gic_deactivate_irq(
        &mut self,
        cpu: usize,
        irq: usize,
        attrs: MemTxAttr,
        interface: &GICv2StateInterface,
    ) {
        if irq >= GIC_MAXIRQ || (!self.gic_is_vcpu(cpu) && irq >= self.num_irq as usize) {
            // 这里处理两种情况:
            // 1. 如果软件写一个虚假中断的 ID(例如 1023) 到 GICC_DIR, GIC 会忽略这个写入.
            // 2. 如果软件写入一个不存在的中断编号, 这必须是"写的值不是一个活动的中断"的字情况.
            // 所以这是不可预测的, 我们选择忽略它. 对于 vcpu, 所有 irq 都可能存在, 因此不适用此限制
            return;
        }

        if !self.gic_eoi_split(cpu, attrs) {
            // 这是不可抵达的, 我们选择忽略它
            log_guest_error!("gic_deactivate_irq: GICC_DIR write when EOIMode clear");
            return;
        }

        if self.gic_is_vcpu(cpu) && !self.gic_virq_is_valid(irq, cpu) {
            // 这个 vIRQ 没有活动或挂起且活动的 LR 条目. 递增 EOICount, 忽略写操作
            let rcpu = self.gic_get_vcpu_real_id(cpu);
            self.h_hcr[rcpu] += 1 << R_GICH_HCR_EOICount_SHIFT;

            // 在维护中断的情况下更新虚拟接口
            self.gic_update_virt(interface);
            return;
        }

        let group = self.gic_has_groups() && self.gic_test_group(irq, cpu);
        if self.gic_cpu_ns_access(cpu, attrs) && !group && debug_gic_enable() {
            println!("Non-secure DI for Group0 interrupt {} ignored", irq);
            return;
        }

        self.gic_clear_active(irq, cpu);
    }

    fn gic_complete_irq(
        &mut self,
        cpu: usize,
        irq: usize,
        attrs: MemTxAttr,
        interface: &GICv2StateInterface,
    ) {
        let cm = 1 << cpu;

        if debug_gic_enable() {
            println!("EOI {}", irq);
        }
        if self.gic_is_vcpu(cpu) {
            // 调用 gic_prio_drop() 将清除 GICH_APR 中的一位, 如果正在运行的 prio < 0x100
            let prio_drop = self.running_priority[cpu] < 100;

            if irq >= GIC_MAXIRQ {
                // 忽略虚假中断
                return;
            }

            self.gic_drop_prio(cpu, 0);

            if !self.gic_eoi_split(cpu, attrs) {
                let valid = self.gic_virq_is_valid(irq, cpu);
                if prio_drop && !valid {
                    // 现在的情况是:
                    // - V_CTRL.EOIMode 为 false,
                    // - 调用 gic_drop_prio() 在 GICH_APR 中清除了一点,
                    // - 此 vIRQ 没有活动或挂起的 LR entry. 在这种情况下, 我们必须增加 EOICount.
                    let rcpu = self.gic_get_vcpu_real_id(cpu);
                    self.h_hcr[rcpu] += 1 << R_GICH_HCR_EOICount_SHIFT;
                } else if valid {
                    self.gic_clear_active(irq, cpu);
                }
            }

            self.gic_update_virt(interface);
            return;
        }

        if irq >= self.num_irq as usize {
            // 处理两种情况:
            // 1. 如果软件将一个伪中断的 ID(如 1023)写入 GICC_EOIR, GIC 将忽略该写入
            // 2. 如果软件写入一个不存在的中断, 这必须是"写入的值与从中断确认寄存器读取的最后一个有效中断值不匹配"的字情况,
            // 所以这是不可预测的. 选择忽略它
            return;
        }

        if self.running_priority[cpu] == 0x100 {
            // 没有活跃的 IRQ
            return;
        }

        if self.revision == REV_11MPCORE as u32 {
            // 如果level触发的中断仍然被触发, 则将其标记为挂起
            if !self.gic_dist_test_edge_trigger(irq)
                && self.gic_dist_test_enabled(irq, cm)
                && self.gic_dist_test_level(irq, cm)
                && (self.gic_dist_target(irq) != 0)
            {
                if debug_gic_enable() {
                    println!("Set {} pending mask 0x{:x}", irq, cm);
                }
                self.gic_dist_set_pending(irq, cm);
            }
        }

        let group = self.gic_has_groups() && self.gic_test_group(irq, cpu);
        if self.gic_cpu_ns_access(cpu, attrs) && !group && debug_gic_enable() {
            println!("Non-secure EOI for Group0 interrupt {} ignored", irq);
            return;
        }

        // 使用 GICC_CTLR 保护 EOI. 当 IRQ 为 group1 时, AckCtl == 0 中断是不可预知的.
        // 我们选择像处理 AckCtl == 1 一样处理它, 即无论如何继续完成 irq.
        self.gic_drop_prio(cpu, if group { 1 } else { 0 });

        // 在 GICv2 中, 客户机可以选择拆分优先级下降和停用
        if self.gic_eoi_split(cpu, attrs) {
            self.gic_clear_active(irq, cpu);
        }
        self.gic_update(interface);
    }

    fn gic_dist_readb(&self, offset: usize, attrs: MemTxAttr) -> u8 {
        let bad_reg = |offset: usize| {
            log_guest_error!("gic_dist_readb: Bad offset 0x{:x}", offset);
            0
        };
        let cpu = self.gic_get_current_cpu();
        let cm = 1 << cpu;
        let mut res = 0;
        if offset < 0x100 {
            // GICD_CTLR
            if offset == 0 {
                // 这里我们依赖于字节 0 中唯一的非零位
                if self.security_extn && !attrs.secure {
                    // 这个寄存器的 NS bank 只是 S bank 版本中 EnableGrp1 位的别名
                    return extract32(self.ctlr, 1, 1) as u8;
                } else {
                    return self.ctlr as u8;
                }
            }

            if offset == 4 {
                // GICD_TYPER byte 0
                return ((self.num_irq / 32 - 1) | (self.num_cpu - 1) << 5) as u8;
            }
            if offset == 5 {
                // GICD_TYPER byte 1
                return (self.security_extn as u8) << 2;
            }
            if (offset == 8) {
                // GICD_IIDR byte 0
                // Arm JEP106 identity
                return 0x3b;
            }
            if (offset == 9) {
                // GICD_IIDR byte 1
                // Arm JEP106 identity
                return 0x04;
            }
            if (offset < 0x0c) {
                // 这个范围内的所有其他字节都是 RAZ
                return 0;
            }
            if offset >= 0x80 {
                // 中断组寄存器: 如果这是对具有安全拓展的 GIC 的 NS 访问,
                // 或者 GIC 根本没有组, 则这些是 RAZ/WI
                res = 0;
                if (!self.security_extn || attrs.secure) && self.gic_has_groups() {
                    // 每个字节偏移量包含 8 个组状态
                    let irq = (offset - 0x080) * 8;
                    if irq >= self.num_irq as usize {
                        return bad_reg(offset);
                    }
                    for i in 0..8 {
                        if self.gic_dist_test_group(irq + i, cm) {
                            res |= 1 << i;
                        }
                    }
                }
                return res;
            }
            return bad_reg(offset);
        } else if offset < 0x200 {
            // 中断 Set/Clear Enable
            let irq = if offset < 0x180 { (offset - 0x100) * 8 } else { (offset - 0x180) * 8 };
            if irq >= self.num_irq as usize {
                return bad_reg(offset);
            }
            res = 0;
            for i in 0..8 {
                if self.security_extn
                    && !attrs.secure
                    && !self.gic_dist_test_group(irq + i, 1 << cpu)
                {
                    // Group0 IRQ 的非安全访问忽略
                    continue;
                }

                if self.gic_dist_test_enabled(irq + i, cm) {
                    res |= 1 << i;
                }
            }
        } else if offset < 0x300 {
            // 中断 Set/Clear Pending
            let irq = if offset < 0x280 { (offset - 0x200) * 8 } else { (offset - 0x280) * 8 };
            if irq >= self.num_irq as usize {
                return bad_reg(offset);
            }
            res = 0;
            let mask = if irq < GIC_INTERNAL { cm } else { ALL_CPU_MASK as u8 };
            for i in 0..8 {
                if self.security_extn
                    && !attrs.secure
                    && !self.gic_dist_test_group(irq + i, 1 << cpu)
                {
                    // Group0 IRQ 的非安全访问忽略
                    continue;
                }

                if self.gic_test_pending(irq + i, mask) {
                    res |= 1 << i;
                }
            }
        } else if offset < 0x400 {
            // 中断 Set/Clear Active
            let irq = if offset < 0x380 {
                (offset - 0x300) * 8
            } else if self.revision == 2 {
                (offset - 0x380) * 8
            } else {
                return bad_reg(offset);
            };
            if irq >= self.num_irq as usize {
                return bad_reg(offset);
            }
            res = 0;
            let mask = if irq < GIC_INTERNAL { cm } else { ALL_CPU_MASK as u8 };
            for i in 0..8 {
                if self.security_extn
                    && !attrs.secure
                    && !self.gic_dist_test_group(irq + i, 1 << cpu)
                {
                    // Group0 IRQ 的非安全访问忽略
                    continue;
                }
                if self.gic_dist_test_active(irq + i, mask) {
                    res |= 1 << i;
                }
            }
        } else if offset < 0x800 {
            // 中断优先级
            let irq = offset - 0x400;
            if irq >= self.num_irq as usize {
                return bad_reg(offset);
            }
            res = self.gic_dist_get_priority(cpu, irq, attrs) as u8;
        } else if offset < 0xc00 {
            // 中断 CPU target
            if self.num_cpu == 1 && self.revision != REV_11MPCORE as u32 {
                // 对于单处理器 IC, 这些是 RAZ/WI
                res = 0;
            } else {
                let irq = offset - 0x800;
                if irq >= self.num_irq as usize {
                    return bad_reg(offset);
                }
                if irq < 29 && self.revision == REV_11MPCORE as u32 {
                    res = 0;
                } else if irq < GIC_INTERNAL {
                    res = cm;
                } else {
                    res = self.gic_dist_target(irq);
                }
            }
        } else if offset < 0xf00 {
            // 中断配置
            let irq = (offset - 0xc00) * 4;
            if irq >= self.num_irq as usize {
                return bad_reg(offset);
            }
            res = 0;
            for i in 0..4 {
                if self.security_extn
                    && !attrs.secure
                    && !self.gic_dist_test_group(irq + i, 1 << cpu)
                {
                    // Group0 IRQ 的非安全访问忽略
                    continue;
                }

                if self.gic_dist_test_model(irq + i) {
                    res |= 1 << (i * 2);
                }
                if self.gic_dist_test_edge_trigger(irq + i) {
                    res |= 2 << (i * 2);
                }
            }
        } else if offset < 0xf10 {
            return bad_reg(offset);
        } else if offset < 0xf30 {
            if self.revision == REV_11MPCORE as u32 {
                return bad_reg(offset);
            }

            let irq = if offset < 0xf20 {
                // GICD_CPENDSGIRn
                offset - 0xf10
            } else {
                offset - 0xf20
                // GICD_SPENDSGIRn
            };

            if self.security_extn && !attrs.secure && !self.gic_dist_test_group(irq, 1 << cpu) {
                // Group0 IRQ 的非安全访问忽略
                res = 0;
            } else {
                res = self.sgi_pending[irq][cpu];
            }
        } else if offset < 0xfd0 {
            return bad_reg(offset);
        } else if offset < 0x1000 {
            if offset & 3 != 0 {
                res = 0;
            } else {
                match self.revision {
                    // REV_11MPCORE
                    0 => {
                        res = GIC_ID_11MPCORE[(offset - 0xfd0) >> 2];
                    },
                    1 => {
                        res = GIC_ID_GICV1[(offset - 0xfd0) >> 2];
                    },
                    2 => {
                        res = GIC_ID_GICV2[(offset - 0xfd0) >> 2];
                    },
                    _ => {
                        res = 0;
                    },
                }
            }
        } else {
            unreachable!();
        }
        res
    }

    fn gic_dist_read(
        &self,
        offset: u64,
        data: &mut u64,
        size: usize,
        attrs: MemTxAttr,
    ) -> MemTxResult {
        match size {
            1 => {
                *data = self.gic_dist_readb(offset as usize, attrs) as u64;
            },
            2 => {
                *data = self.gic_dist_readb(offset as usize, attrs) as u64;
                *data |= (self.gic_dist_readb(offset as usize + 1, attrs) as u64) << 8;
            },
            4 => {
                *data = self.gic_dist_readb(offset as usize, attrs) as u64;
                *data |= (self.gic_dist_readb(offset as usize + 1, attrs) as u64) << 8;
                *data |= (self.gic_dist_readb(offset as usize + 2, attrs) as u64) << 16;
                *data |= (self.gic_dist_readb(offset as usize + 3, attrs) as u64) << 24;
            },
            _ => {
                return MemTxResult::MemTxError;
            },
        }

        GICv2Trace::trace_gic_dist_read(&(offset as usize), &size, &(*data as usize));

        MemTxResult::MemTxOk
    }

    fn gic_dist_writeb(
        &mut self,
        offset: usize,
        mut value: u32,
        attrs: MemTxAttr,
        interface: &GICv2StateInterface,
    ) {
        let bad_reg = |offset: usize| {
            log_guest_error!("gic_dist_writeb: Bad offset 0x{:x}", offset);
        };
        let cpu = self.gic_get_current_cpu();
        if offset < 0x100 {
            if offset == 0 {
                if self.security_extn && !attrs.secure {
                    // NS 版本只是 S 版本 bit1 的别名
                    self.ctlr = deposit32(self.ctlr, 1, 1, value);
                } else if self.gic_has_groups() {
                    self.ctlr = value & (GICD_CTLR_EN_GRP0 | GICD_CTLR_EN_GRP1) as u32;
                } else {
                    self.ctlr = value & GICD_CTLR_EN_GRP0 as u32;
                }
                if debug_gic_enable() {
                    println!(
                        "Distributor: Group0 {}abled; Group 1 {}abled",
                        if self.ctlr & GICD_CTLR_EN_GRP0 as u32 != 0 { "En" } else { "Dis" },
                        if self.ctlr & GICD_CTLR_EN_GRP1 as u32 != 0 { "En" } else { "Dis" }
                    );
                }
            } else if offset < 4 {
                // 忽略
            } else if offset >= 0x80 {
                // 中断组寄存器: 用于 NS 访问安全 GIC 的 RAZ/WI, 或用于没有组的 GIC.
                if (!self.security_extn || attrs.secure) && self.gic_has_groups() {
                    // 每个字节偏移量包含 8 个组状态位
                    let irq = (offset - 0x80) * 8;
                    if irq >= self.num_irq as usize {
                        return bad_reg(offset);
                    }
                    for i in 0..8 {
                        // 组bits用于私有中断
                        let cm = if irq < GIC_INTERNAL { 1 << cpu } else { ALL_CPU_MASK } as u8;
                        if value & (1 << i) != 0 {
                            // Group1(Non-secure)
                            self.gic_dist_set_group(irq + i, cm);
                        } else {
                            // Group0(Secure)
                            self.gic_dist_clear_group(irq + i, cm);
                        }
                    }
                }
            } else {
                return bad_reg(offset);
            }
        } else if offset < 0x180 {
            // 中断 Set Enable
            let irq = (offset - 0x100) * 8;
            if irq >= self.num_irq as usize {
                return bad_reg(offset);
            }
            if irq < GIC_NR_SGIS {
                value = 0xff;
            }

            for i in 0..8 {
                if value & (1 << i) != 0 {
                    let mask =
                        if irq < GIC_INTERNAL { 1 << cpu } else { self.gic_dist_target(irq + i) };
                    let cm = if irq < GIC_INTERNAL { 1 << cpu } else { ALL_CPU_MASK } as u8;

                    if self.security_extn
                        && !attrs.secure
                        && !self.gic_dist_test_group(irq + i, 1 << cpu)
                    {
                        // Group0 IRQ 的非安全访问忽略
                        continue;
                    }

                    if !self.gic_dist_test_enabled(irq + i, cm) {
                        if debug_gic_enable() {
                            println!("Enabled IRQ {}", irq + i);
                        }
                        GICv2Trace::trace_gic_enable_irq(&(irq + i));
                    }
                    self.gic_dist_set_enabled(irq + i, cm);
                    // 如果升高的level触发 IRQ 启用, 则标记为 pending
                    if self.gic_dist_test_level(irq + i, mask)
                        && !self.gic_dist_test_edge_trigger(irq + i)
                    {
                        if debug_gic_enable() {
                            println!("Set {} pending mask 0x:{:x}", irq + i, mask);
                        }
                        self.gic_dist_set_pending(irq + i, mask);
                    }
                }
            }
        } else if offset < 0x200 {
            // 中断 Clear Enable
            let irq = (offset - 0x180) * 8;
            if irq >= self.num_irq as usize {
                return bad_reg(offset);
            }
            if irq < GIC_NR_SGIS {
                value = 0;
            }

            for i in 0..8 {
                if value & (1 << i) != 0 {
                    let cm = if irq < GIC_INTERNAL { 1 << cpu } else { ALL_CPU_MASK } as u8;

                    if self.security_extn
                        && !attrs.secure
                        && !self.gic_dist_test_group(irq + i, 1 << cpu)
                    {
                        // Group0 IRQ 的非安全访问忽略
                        continue;
                    }

                    if self.gic_dist_test_enabled(irq + i, cm) {
                        if debug_gic_enable() {
                            println!("Disabled IRQ {}", irq + i);
                        }
                        GICv2Trace::trace_gic_disable_irq(&(irq + i));
                    }
                    self.gic_dist_clear_enabled(irq + i, cm);
                }
            }
        } else if offset < 0x280 {
            // 中断 Set Pending
            let irq = (offset - 0x200) * 8;
            if irq >= self.num_irq as usize {
                return bad_reg(offset);
            }
            if irq < GIC_INTERNAL {
                value = 0;
            }

            for i in 0..8 {
                if value & (1 << i) != 0 {
                    if self.security_extn
                        && !attrs.secure
                        && !self.gic_dist_test_group(irq + i, 1 << cpu)
                    {
                        // Group0 IRQ 的非安全访问忽略
                        continue;
                    }
                    self.gic_dist_set_pending(irq + i, self.gic_dist_target(irq + i));
                }
            }
        } else if offset < 0x300 {
            // 中断 Clear Pending
            let irq = (offset - 0x280) * 8;
            if irq >= self.num_irq as usize {
                return bad_reg(offset);
            }
            if irq < GIC_NR_SGIS {
                value = 0;
            }

            for i in 0..8 {
                if self.security_extn
                    && !attrs.secure
                    && !self.gic_dist_test_group(irq + i, 1 << cpu)
                {
                    // Group0 IRQ 的非安全访问忽略
                    continue;
                }

                // ??? 这将清除所有 cpu 的挂起位, 甚至是每个 cpu 的中断. 目前尚不清楚这是否是正确的行为.
                if value & (1 << i) != 0 {
                    self.gic_dist_clear_pending(irq + i, ALL_CPU_MASK as u8);
                }
            }
        } else if offset < 0x380 {
            // 中断 Set Active
            if self.revision != 2 {
                return bad_reg(offset);
            }

            let irq = (offset - 0x300) * 8;
            if irq >= self.num_irq as usize {
                return bad_reg(offset);
            }

            // 这个寄存器 banked 每个 cpu(PPIs)
            let cm = if irq < GIC_INTERNAL { 1 << cpu } else { ALL_CPU_MASK } as u8;

            for i in 0..8 {
                if self.security_extn && !attrs.secure && !self.gic_dist_test_group(irq + i, cm) {
                    // Group0 IRQ 的非安全访问忽略
                    continue;
                }

                if value & (1 << i) != 0 {
                    self.gic_dist_set_active(irq + i, cm);
                }
            }
        } else if offset < 0x400 {
            // 中断 Clear Active
            if self.revision != 2 {
                return bad_reg(offset);
            }

            let irq = (offset - 0x380) * 8;
            if irq >= self.num_irq as usize {
                return bad_reg(offset);
            }

            // 这个寄存器 banked 每个 cpu(PPIs)
            let cm = if irq < GIC_INTERNAL { 1 << cpu } else { ALL_CPU_MASK } as u8;

            for i in 0..8 {
                if self.security_extn
                    && !attrs.secure
                    && !self.gic_dist_test_group(irq + i, 1 << cpu)
                {
                    // Group0 IRQ 的非安全访问忽略
                    continue;
                }

                if value & (1 << i) != 0 {
                    self.gic_dist_clear_active(irq + i, cm);
                }
            }
        } else if offset < 0x800 {
            // 中断优先级
            let irq = offset - 0x400;
            if irq >= self.num_irq as usize {
                return bad_reg(offset);
            }
            self.gic_dist_set_priority(cpu, irq, value as u8, attrs);
        } else if offset < 0xc00 {
            // 中断 CPU target. RAZ/WI 在单处理器的 GIC 上, 除了恼人的 11MPCore 的 GIC.
            if self.num_cpu != 1 || self.revision == REV_11MPCORE as u32 {
                let irq = offset - 0x800;
                if irq >= self.num_irq as usize {
                    return bad_reg(offset);
                }
                if irq < 29 && self.revision == REV_11MPCORE as u32 {
                    value = 0;
                } else if irq < GIC_INTERNAL {
                    value = ALL_CPU_MASK as u32;
                }
                self.irq_target[irq] = (value & ALL_CPU_MASK as u32) as u8;
            }
        } else if offset < 0xf00 {
            // 中断配置
            let irq = (offset - 0xc00) * 4;
            if irq >= self.num_irq as usize {
                return bad_reg(offset);
            }
            if irq < GIC_INTERNAL {
                value |= 0xaa;
            }
            for i in 0..4 {
                if self.security_extn
                    && !attrs.secure
                    && !self.gic_dist_test_group(irq + i, 1 << cpu)
                {
                    // Group0 IRQ 的非安全访问忽略
                    continue;
                }

                if self.revision == REV_11MPCORE as u32 {
                    if value & (1 << (i * 2)) != 0 {
                        self.gic_dist_set_model(irq + i);
                    } else {
                        self.gic_dist_clear_model(irq + i);
                    }
                }
                if value & (2 << (i * 2)) != 0 {
                    self.gic_dist_set_edge_trigger(irq + i);
                } else {
                    self.gic_dist_clear_edge_trigger(irq + i);
                }
            }
        } else if offset < 0xf10 {
            // 0xf00只处理32位的写操作
            return bad_reg(offset);
        } else if offset < 0xf20 {
            // GICD_CPENDSGIRn
            if self.revision == REV_11MPCORE as u32 {
                return bad_reg(offset);
            }
            let irq = offset - 0xf10;

            if !self.security_extn || attrs.secure || self.gic_dist_test_group(irq, 1 << cpu) {
                self.sgi_pending[irq][cpu] &= !(value as u8);
                if self.sgi_pending[irq][cpu] == 0 {
                    self.gic_dist_clear_pending(irq, 1 << cpu);
                }
            }
        } else if offset < 0xf30 {
            // GICD_SPENDSGIRn
            if self.revision == REV_11MPCORE as u32 {
                return bad_reg(offset);
            }
            let irq = offset - 0xf20;

            if !self.security_extn || attrs.secure || self.gic_dist_test_group(irq, 1 << cpu) {
                self.gic_dist_set_pending(irq, 1 << cpu);
                self.sgi_pending[irq][cpu] |= value as u8;
            }
        } else {
            return bad_reg(offset);
        }
        self.gic_update(interface);
    }

    fn gic_dist_writew(
        &mut self,
        offset: usize,
        value: u32,
        attrs: MemTxAttr,
        interface: &GICv2StateInterface,
    ) {
        self.gic_dist_writeb(offset, value & 0xff, attrs, interface);
        self.gic_dist_writeb(offset + 1, value >> 8, attrs, interface);
    }

    fn gic_dist_writel(
        &mut self,
        offset: usize,
        value: u32,
        attrs: MemTxAttr,
        interface: &GICv2StateInterface,
    ) {
        if offset == 0x100 {
            let cpu = self.gic_get_current_cpu();
            let irq = value as usize & 0xf;
            let mut mask = match (value >> 24) & 3 {
                0 => (value >> 16) & ALL_CPU_MASK as u32,
                1 => ALL_CPU_MASK as u32 ^ (1 << cpu),
                2 => 1 << cpu,
                _ => {
                    if debug_gic_enable() {
                        println!("Bad Soft Int target filter");
                    }
                    ALL_CPU_MASK as u32
                },
            } as u8;
            self.gic_dist_set_pending(irq, mask);
            let mut target_cpu = mask.trailing_zeros() as usize;
            while target_cpu < GIC_NCPU {
                self.sgi_pending[irq][target_cpu] |= 1 << cpu;
                mask &= !(1 << target_cpu);
                target_cpu = mask.trailing_zeros() as usize;
            }
            self.gic_update(interface);
            return;
        }
        self.gic_dist_writew(offset, value & 0xffff, attrs, interface);
        self.gic_dist_writew(offset + 2, value >> 16, attrs, interface);
    }

    fn gic_dist_write(
        &mut self,
        offset: u64,
        data: u64,
        size: usize,
        attrs: MemTxAttr,
        interface: &GICv2StateInterface,
    ) -> MemTxResult {
        GICv2Trace::trace_gic_dist_write(&(offset as usize), &size, &(data as usize));

        match size {
            1 => {
                self.gic_dist_writeb(offset as usize, data as u32, attrs, interface);
            },
            2 => {
                self.gic_dist_writew(offset as usize, data as u32, attrs, interface);
            },
            4 => {
                self.gic_dist_writel(offset as usize, data as u32, attrs, interface);
            },
            _ => {
                return MemTxResult::MemTxError;
            },
        }
        MemTxResult::MemTxOk
    }

    #[inline]
    fn gic_apr_ns_view(&self, cpu: usize, regno: usize) -> u32 {
        match GIC_MIN_BPR {
            0 => {
                if regno < 2 {
                    return self.nsapr[regno + 2][cpu];
                }
            },
            1 => {
                if regno == 0 {
                    return self.nsapr[regno + 1][cpu];
                }
            },
            2 => {
                if regno == 0 {
                    return extract32(self.nsapr[0][cpu], 16, 16);
                }
            },
            3 => {
                if regno == 0 {
                    return extract32(self.nsapr[0][cpu], 8, 8);
                }
            },
            _ => {
                unreachable!()
            },
        }
        0
    }

    #[inline]
    fn gic_apr_write_ns_view(&mut self, cpu: usize, regno: usize, value: u32) {
        match GIC_MIN_BPR {
            0 => {
                if regno < 2 {
                    self.nsapr[regno + 2][cpu] = value;
                }
            },
            1 => {
                if regno == 0 {
                    self.nsapr[regno + 1][cpu] = value;
                }
            },
            2 => {
                if regno == 0 {
                    self.nsapr[0][cpu] = deposit32(self.nsapr[0][cpu], 16, 16, value);
                }
            },
            3 => {
                if regno == 0 {
                    self.nsapr[0][cpu] = deposit32(self.nsapr[0][cpu], 8, 8, value);
                }
            },
            _ => {
                unreachable!()
            },
        }
    }

    fn gic_cpu_read(
        &mut self,
        cpu: usize,
        offset: u64,
        data: &mut u64,
        attrs: MemTxAttr,
        interface: &GICv2StateInterface,
    ) -> MemTxResult {
        match offset {
            // Control
            0x00 => {
                *data = self.gic_get_cpu_control(cpu, attrs) as u64;
            },
            // Priority mask
            0x04 => {
                *data = self.gic_get_priority_mask(cpu, attrs) as u64;
            },
            // Binary Point
            0x08 => {
                if self.gic_cpu_ns_access(cpu, attrs) {
                    if self.cpu_ctlr[cpu] & GICC_CTLR_CBPR as u32 != 0 {
                        *data = (self.bpr[cpu] + 1).min(7) as u64;
                    } else {
                        *data = self.abpr[cpu] as u64;
                    }
                } else {
                    *data = self.bpr[cpu] as u64;
                }
            },
            // Acknowledge
            0x0c => {
                *data = self.gic_acknowledge_irq(cpu, attrs, interface) as u64;
            },
            // Running Priority
            0x14 => {
                *data = self.gic_get_running_priority(cpu, attrs) as u64;
            },
            // Highest Pending Interrupt
            0x18 => {
                *data = self.gic_get_current_pending_irq(cpu, attrs) as u64;
            },
            // Aliased Binary Point
            0x1c => {
                // GIC v2, no security: ABPR
                // GIC v1, no security: not implemented (RAZ/WI)
                // With security extensions, secure access: ABPR (alias of NS BPR)
                // With security extensions, nonsecure access: RAZ/WI
                if !self.gic_has_groups() || self.gic_cpu_ns_access(cpu, attrs) {
                    *data = 0;
                } else {
                    *data = self.abpr[cpu] as u64;
                }
            },
            0xd0 | 0xd4 | 0xd8 | 0xdc => {
                let regno = (offset - 0xd0) / 4;
                let nr_aprs = if self.gic_is_vcpu(cpu) { GIC_VIRT_NR_APRS } else { GIC_NR_APRS };

                if regno as usize >= nr_aprs || self.revision != 2 {
                    *data = 0;
                } else if self.gic_is_vcpu(cpu) {
                    *data = self.h_apr[self.gic_get_vcpu_real_id(cpu)] as u64;
                } else if self.gic_cpu_ns_access(cpu, attrs) {
                    *data = self.gic_apr_ns_view(regno as usize, cpu) as u64;
                } else {
                    *data = self.apr[regno as usize][cpu] as u64;
                }
            },
            0xe0 | 0xe4 | 0xe8 | 0xec => {
                let regno = (offset - 0xe0) / 4;
                if regno as usize >= GIC_NR_APRS
                    || self.revision != 2
                    || !self.gic_has_groups()
                    || self.gic_cpu_ns_access(cpu, attrs)
                    || self.gic_is_vcpu(cpu)
                {
                    *data = 0;
                } else {
                    *data = self.nsapr[regno as usize][cpu] as u64;
                }
            },
            0xfc => {
                if self.revision == REV_11MPCORE as u32 {
                    // Reserved on 11MPCore
                    *data = 0;
                } else {
                    // GICv1 or v2; Arm implementation
                    *data = (self.revision << 16 | 0x43b) as u64;
                }
            },
            _ => {
                log_guest_error!("gic_cpu_read: Bad offset 0x{:x}", offset);
                *data = 0;
            },
        }

        let s = if self.gic_is_vcpu(cpu) { String::from("vcpu") } else { String::from("cpu") };
        GICv2Trace::trace_gic_cpu_read(&s, &cpu as &usize, &(offset as usize), &(*data as usize));

        MemTxResult::MemTxOk
    }

    fn gic_cpu_write(
        &mut self,
        cpu: usize,
        offset: usize,
        value: u32,
        attrs: MemTxAttr,
        interface: &GICv2StateInterface,
    ) -> MemTxResult {
        let s = if self.gic_is_vcpu(cpu) { String::from("vcpu") } else { String::from("cpu") };
        GICv2Trace::trace_gic_cpu_write(
            &s,
            &self.gic_get_vcpu_real_id(cpu),
            &offset,
            &(value as usize),
        );

        match offset {
            // Control
            0x00 => {
                self.gic_set_cpu_control(cpu, value, attrs);
            },
            // Priority mask
            0x04 => {
                self.gic_set_priority_mask(cpu, value as u8, attrs);
            },
            // Binary Point
            0x08 => {
                if self.gic_cpu_ns_access(cpu, attrs) {
                    if self.cpu_ctlr[cpu] & GICC_CTLR_CBPR as u32 != 0 {
                        return MemTxResult::MemTxOk;
                    } else {
                        self.abpr[cpu] = (value as u8 & 0x7).max(GIC_MIN_ABPR as u8);
                    }
                } else {
                    let min_bpr =
                        if self.gic_is_vcpu(cpu) { GIC_VIRT_MIN_BPR } else { GIC_MIN_BPR };
                    self.bpr[cpu] = (value & 0x7).max(min_bpr as u32) as u8;
                }
            },
            // End Of Interrupt
            0x10 => {
                self.gic_complete_irq(cpu, value as usize & 0x3ff, attrs, interface);
                return MemTxResult::MemTxOk;
            },
            // Aliased Binary Point
            0x1c => {
                if !self.gic_has_groups() || self.gic_cpu_ns_access(cpu, attrs) {
                    // unimplemented, or NS access: RAZ/WI
                    return MemTxResult::MemTxOk;
                } else {
                    self.abpr[cpu] = (value as u8 & 0x7).max(GIC_MIN_ABPR as u8);
                }
            },
            0xd0 | 0xd4 | 0xd8 | 0xdc => {
                let regno = (offset - 0xd0) / 4;
                let nr_aprs = if self.gic_is_vcpu(cpu) { GIC_VIRT_NR_APRS } else { GIC_NR_APRS };

                if regno >= nr_aprs || self.revision != 2 {
                    return MemTxResult::MemTxOk;
                }
                if self.gic_is_vcpu(cpu) {
                    self.h_apr[self.gic_get_vcpu_real_id(cpu)] = value;
                } else if self.gic_cpu_ns_access(cpu, attrs) {
                    self.gic_apr_write_ns_view(regno, cpu, value);
                } else {
                    self.apr[regno][cpu] = value;
                }
                self.running_priority[cpu] = self.gic_get_prio_from_apr_bits(cpu) as u16;
            },
            0xe0 | 0xe4 | 0xe8 | 0xec => {
                let regno = (offset - 0xe0) / 4;
                if regno >= GIC_NR_APRS || self.revision != 2 {
                    return MemTxResult::MemTxOk;
                }
                if self.gic_is_vcpu(cpu) {
                    return MemTxResult::MemTxOk;
                }
                if !self.gic_has_groups() || self.gic_cpu_ns_access(cpu, attrs) {
                    return MemTxResult::MemTxOk;
                }
                self.nsapr[regno][cpu] = value;
                self.running_priority[cpu] = self.gic_get_prio_from_apr_bits(cpu) as u16;
            },
            // GICC_DIR
            0x1000 => {
                self.gic_deactivate_irq(cpu, value as usize & 0x3ff, attrs, interface);
            },
            _ => {
                log_guest_error!("gic_cpu_write: Bad offset 0x:{:x}", offset);
                return MemTxResult::MemTxOk;
            },
        }

        if self.gic_is_vcpu(cpu) {
            self.gic_update_virt(interface);
        } else {
            self.gic_update(interface);
        }

        MemTxResult::MemTxOk
    }

    fn gic_thiscpu_read(
        &mut self,
        offset: u64,
        data: &mut u64,
        attrs: MemTxAttr,
        interface: &GICv2StateInterface,
    ) -> MemTxResult {
        self.gic_cpu_read(self.gic_get_current_cpu(), offset, data, attrs, interface)
    }

    fn gic_thiscpu_write(
        &mut self,
        offset: usize,
        value: u32,
        attrs: MemTxAttr,
        interface: &GICv2StateInterface,
    ) -> MemTxResult {
        self.gic_cpu_write(self.gic_get_current_cpu(), offset, value, attrs, interface)
    }

    fn gic_thisvcpu_read(
        &mut self,
        offset: u64,
        data: &mut u64,
        attrs: MemTxAttr,
        interface: &GICv2StateInterface,
    ) -> MemTxResult {
        self.gic_cpu_read(self.gic_get_current_vcpu(), offset, data, attrs, interface)
    }

    fn gic_thisvcpu_write(
        &mut self,
        offset: usize,
        value: u32,
        attrs: MemTxAttr,
        interface: &GICv2StateInterface,
    ) -> MemTxResult {
        self.gic_cpu_write(self.gic_get_current_vcpu(), offset, value, attrs, interface)
    }

    fn gic_compute_eisr(&self, cpu: usize, lr_start: usize) -> u32 {
        let mut ret = 0;
        for lr_idx in 0..self.num_lrs as usize {
            let entry = &self.h_lr[lr_idx][cpu];
            ret = deposit32(ret, lr_idx - lr_start, 1, self.gic_lr_entry_is_eoi(*entry) as u32);
        }
        ret
    }

    fn gic_compute_elrsr(&self, cpu: usize, lr_start: usize) -> u32 {
        let mut ret = 0;
        for lr_idx in 0..self.num_lrs as usize {
            let entry = &self.h_lr[lr_idx][cpu];
            ret = deposit32(ret, lr_idx - lr_start, 1, self.gic_lr_entry_is_free(*entry) as u32);
        }
        ret
    }

    fn gic_vmcr_write(&mut self, value: u32, attrs: MemTxAttr) {
        let vcpu = self.gic_get_current_vcpu();

        let ctlr = extract32(value, 0, 10);
        let abpr = extract32(value, 18, 3);
        let bpr = extract32(value, 21, 3);
        let prio_mask = extract32(value, 27, 5) << 3;

        self.gic_set_cpu_control(vcpu, ctlr, attrs);
        self.abpr[vcpu] = abpr.max(GIC_VIRT_MIN_ABPR as u32) as u8;
        self.bpr[vcpu] = bpr.max(GIC_VIRT_MIN_BPR as u32) as u8;
        self.gic_set_priority_mask(vcpu, prio_mask as u8, attrs);
    }

    fn gic_hyp_read(
        &self,
        cpu: usize,
        offset: usize,
        data: &mut u64,
        attrs: MemTxAttr,
    ) -> MemTxResult {
        let vcpu = cpu + GIC_NCPU;

        match offset {
            // Hypervisor Control
            0 => {
                *data = self.h_hcr[cpu] as u64;
            },
            // VGIC Type
            4 => {
                *data = deposit32(0, 0, 6, self.num_lrs - 1) as u64;
                *data =
                    deposit32(*data as u32, 26, 3, GIC_VIRT_MAX_GROUP_PRIO_BITS as u32 - 1) as u64;
                *data = deposit32(*data as u32, 29, 3, (7 - GIC_VIRT_MIN_BPR as u32) - 1) as u64;
            },
            // Virtual Machine Control
            8 => {
                *data = deposit32(0, 0, 10, extract32(self.cpu_ctlr[vcpu], 0, 10)) as u64;
                *data = deposit32(*data as u32, 18, 3, self.abpr[vcpu] as u32) as u64;
                *data = deposit32(*data as u32, 21, 3, self.bpr[vcpu] as u32) as u64;
                *data = deposit32(
                    *data as u32,
                    27,
                    5,
                    extract32(self.priority_mask[vcpu] as u32, 3, 5),
                ) as u64;
            },
            // Maintenance Interrupt Status
            16 => {
                *data = self.h_misr[cpu] as u64;
            },
            // End of Interrupt Status 0 and 1
            32 | 36 => {
                *data = self.gic_compute_eisr(cpu, (offset - 32) * 8) as u64;
            },
            // Empty List Status 0 and 1
            48 | 52 => {
                *data = self.gic_compute_elrsr(cpu, (offset - 48) * 8) as u64;
            },
            // Active Priorities
            240 => {
                *data = self.h_apr[cpu] as u64;
            },
            // List Registers
            256..=508 => {
                let lr_idx = (offset - 256) / 4;

                if lr_idx > self.num_lrs as usize {
                    *data = 0;
                } else {
                    *data = self.h_lr[lr_idx][cpu] as u64;
                }
            },
            _ => {
                log_guest_error!("gic_hyp_read: Bad offset 0x{:x}", offset);
            },
        }

        GICv2Trace::trace_gic_hyp_read(&offset, &(*data as usize));

        MemTxResult::MemTxOk
    }

    fn gic_hyp_write(
        &mut self,
        cpu: usize,
        offset: usize,
        value: u32,
        attrs: MemTxAttr,
        interface: &GICv2StateInterface,
    ) -> MemTxResult {
        let vcpu = cpu + GIC_NCPU;

        GICv2Trace::trace_gic_hyp_write(&offset, &(value as usize));

        match offset {
            // Hypervisor Control
            0 => {
                self.h_hcr[cpu] = value & GICH_HCR_MASK;
            },
            // Virtual Machine Control
            8 => {
                self.gic_vmcr_write(value, attrs);
            },
            // Active Priorities
            240 => {
                self.h_apr[cpu] = value;
                self.running_priority[vcpu] = self.gic_get_prio_from_apr_bits(vcpu) as u16;
            },
            // List Registers
            256..=508 => {
                let lr_idx = (offset - 256) / 4;
                if lr_idx > self.num_lrs as usize {
                    return MemTxResult::MemTxOk;
                }

                self.h_lr[lr_idx][cpu] = value & GICH_LR_MASK;
                GICv2Trace::trace_gic_lr_entry(&cpu, &lr_idx, &(self.h_lr[lr_idx][cpu] as usize));
            },
            _ => {
                log_guest_error!("gic_hyp_write: Bad offset 0x{:x}", offset);
                return MemTxResult::MemTxOk;
            },
        }

        self.gic_update_virt(interface);

        MemTxResult::MemTxOk
    }

    fn gic_thiscpu_hyp_read(&self, offset: usize, data: &mut u64, attrs: MemTxAttr) -> MemTxResult {
        self.gic_hyp_read(self.gic_get_current_cpu(), offset, data, attrs)
    }

    fn gic_thiscpu_hyp_write(
        &mut self,
        offset: usize,
        value: u32,
        attrs: MemTxAttr,
        interface: &GICv2StateInterface,
    ) -> MemTxResult {
        self.gic_hyp_write(self.gic_get_current_cpu(), offset, value, attrs, interface)
    }

    fn arm_gic_realize(&mut self) {
        self.arm_gic_common_realize();
        if self.n_prio_bits > GIC_MAX_PRIORITY_BITS as u32
            || (if self.virt_extn {
                self.n_prio_bits < GIC_VIRT_MAX_GROUP_PRIO_BITS as u32
            } else {
                self.n_prio_bits < GIC_MIN_PRIORITY_BITS as u32
            })
        {
            log_faltal!(
                "num-priority-bits cannot be greater than {} or less than {}",
                GIC_MAX_PRIORITY_BITS,
                if self.virt_extn { GIC_VIRT_MAX_GROUP_PRIO_BITS } else { GIC_MIN_PRIORITY_BITS }
            );
        }
    }
}
